package com.adjy.pathbuilders.scenario.internal;

import static com.adjy.pathbuilders.commons.Preconditions.checkNotNull;

import com.adjy.pathbuilders.commons.InvalidSourceException;
import com.adjy.pathbuilders.scenario.Position;

/**
 * A simple implementation of Position.
 */
public class DefaultPosition implements Position {

	private int x;
	private int y;
	
	private static final String FIELD_SEPARATOR = ";";
	
	public DefaultPosition(int x, int y) {
		this.x = x;
		this.y = y;
	}
	
	@Override
	public int getX() {
		return x;
	}

	@Override
	public int getY() {
		return y;
	}

	@Override
	public void setX(int x) {
		this.x = x;
	}

	@Override
	public void setY(int y) {
		this.y = y;
	}

	@Override
	public String toStore() {
		return x + FIELD_SEPARATOR + y;
	}
	
	/**
	 * This method creates a Position object with a {@link String} generated by the 
	 * toStore method of this class or follow the same pattern.
	 * @param source The source {@link String}
	 * @return a {@link Position} object which contains the data of the given source.
	 * @throws InvalidSourceException if any element is missing. This may occur if
	 * the given source was not generated using the pattern used by toStore.
	 */
	public static Position load(String source) throws InvalidSourceException {
		checkNotNull(source, "source must not be null.");
		
		String[] tokens = source.split(FIELD_SEPARATOR);
		checkTokens(source, tokens);
		
		int x = (int) (tryReadInt(tokens[0], source) * 100f / 1000f);
		int y = (int) (tryReadInt(tokens[1], source) * 62.5f / 625f);

		return new DefaultPosition(x, y);
	}

	private static void checkTokens(String source, String[] tokens)
			throws InvalidSourceException {
		if (tokens.length != 2) {
			throw new InvalidSourceException(source);
		}
	}
	
	private static int tryReadInt(String token, String source) throws InvalidSourceException {
		try {
			return Integer.parseInt(token);
		} catch (NumberFormatException e) {
			throw new InvalidSourceException(source);
		}
	}
	
	@Override
	public boolean equals(Object o) {
		if(!(o instanceof DefaultPosition)) return false;
		return o!= null && getX() == ((DefaultPosition) o).getX() && getY() == ((DefaultPosition) o).getY();
	}
}
